package com.telnetnz.ticketdesk.action.acp.user;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.rockbb.common.simpleframe.config.SimpleConfig;
import com.rockbb.common.sso.acl.ACLBuilder;
import com.rockbb.common.utilities.security.StringDigest;
import com.rockbb.common.utilities.text.ComponentBuilder;
import com.rockbb.common.utilities.text.StringUtils;
import com.telnetnz.ticketdesk.action.base.BasicSessionPageAcpAction;
import com.telnetnz.ticketdesk.action.common.CommonUtils;
import com.telnetnz.ticketdesk.bean.User;
import com.telnetnz.ticketdesk.service.OperationLogService;
import com.telnetnz.ticketdesk.service.ProjectToUserService;
import com.telnetnz.ticketdesk.service.UserService;

public class AcpUserEditAction extends BasicSessionPageAcpAction
{
	private static Logger logger = Logger.getLogger(AcpUserEditAction.class);

	public String doDeleteMember()
	{
		return SUCCESS;
	}

	public String doBan()
	{
		RequestBean bean = new DefaultRequestBean();
		long id = bean.getLong("id", 0L);
		User user = UserService.getUser(id);
		if (user != null)
		{
			updateUserStatus(user, UserService.USER_STATUS_INACTIVATED);
			OperationLogService.addLog(
					OperationLogService.OBJECT_TYPE_USER,
					id,
					getSession().getSession_uuid(),
					getContext().getActionName(),
					null);
		}

		return redirect(bean.getRedirect());
	}

	public String doUnban()
	{
		RequestBean bean = new DefaultRequestBean();
		long id = bean.getLong("id", 0L);
		User user = UserService.getUser(id);
		if (user != null)
		{
			updateUserStatus(user, UserService.USER_STATUS_NORMAL);
			OperationLogService.addLog(
					OperationLogService.OBJECT_TYPE_USER,
					id,
					getSession().getSession_uuid(),
					getContext().getActionName(),
					null);
		}

		return redirect(bean.getRedirect());
	}

	public String doEdit()
	{
		UserEditBean bean = new UserEditBean();

		if (bean.getUser() == null)
		{
			return this.message_box(
					langRes.get("global.operation-fail"),
					langRes.get("user.user-not-exist", new String[]{bean.getRedirect()}),
					bean.getRedirect(),
					2);
		}

		if (bean.isSubmitted() && bean.validate())
		{
			if(bean.getUser().getId() == 0)
			{
				UserService.addUser(bean.getUser());

				OperationLogService.addLog(
						OperationLogService.OBJECT_TYPE_USER,
						bean.getUser().getId(),
						getSession().getSession_uuid(),
						getContext().getActionName(),
						OperationLogService.createSimpleDiff("name", new String[]{"null", bean.getUser().getName()}));

				return this.message_box(
						langRes.get("admin.user-add-success"), 
						langRes.get("admin.user-add-success-message", new String[]{bean.getRedirect()}),
						bean.getRedirect(),
						2
					);
			}
			else
			{
				UserService.updateUser(bean.getUser());

				OperationLogService.addLog(
						OperationLogService.OBJECT_TYPE_USER,
						bean.getUser().getId(),
						getSession().getSession_uuid(),
						getContext().getActionName(),
						null);

				return this.message_box(
						langRes.get("global.operation-success"), 
						langRes.get("admin.user-update-success-message", new String[]{bean.getRedirect()}),
						bean.getRedirect(),
						3
					);
			}
		}

		this.put_page_key("bean", bean);
		this.put_page_key("post_action", baseLink());

		// Language options
		this.put_page_key("language_options", CommonUtils.buildLanguageDropdown(SimpleConfig.getLanguages(), bean.getUser().getLanguage(), false));
		// Time zone options
		this.put_page_key("timezone_options", CommonUtils.buildTimezoneDropdown(langRes, bean.getUser().getTimezone()));
		// Permissions
		this.put_page_key("permission_rows", buildPermissionOptions(bean.getUser().getPermissions(), "permissions"));
		// Status
		this.put_page_key("status_options", CommonUtils.buildSingleDropdown(langRes, "user.status.", UserService.STATUSES, bean.getUser().getStatus(), false));

		return INPUT;
	}

	public class UserEditBean extends RequestBean
	{
		private User user;
		private String passwd;
		private String passwd_confirm;
		private int[] permissions;

		public User getUser() {
			return user;
		}

		public int[] getPermissions() {
			return permissions;
		}

		@Override
		protected void loadRequest(){
			long id = getLong("id", 0L);
			if (id == 0) {
				user = new User();
				user.initialize();
			} else {
				user = UserService.getRawUser(id);
			}

			if (user != null)
			{
				passwd = get("passwd");
				passwd_confirm = get("passwd_confirm");
				permissions = getIntArray("permissions", new int[]{},SimpleConfig.getRoleIndexes().toArray(new Integer[]{}));

				if (isSubmitted())
				{
					user.setName(get("username"));
					user.setEmail(get("useremail").toLowerCase());
					user.setLanguage(getInt("language", 0, 0, getLanguages().size()-1));
					user.setTimezone(
							getFloat("timezone", UserService.USER_TZONE_ANONYMOUS, UserService.USER_TIMEZONE_KEYS));
					user.setStatus(getInt("userstatus", 0, 0, UserService.STATUSES.length-1));
					user.setPermissions(ACLBuilder.permissionsToString(permissions));
				}
			}
		}

		@Override
		protected boolean validate()
		{
			boolean flag = true;

			// User name
			if (user.getName().length() == 0)
			{
				flag = false;
				this.put_error_msg("username", langRes.get("global.content-cannot-be-empty"));
			}
			else
			{
				String regex = "^[\\w\\-\\.]{3,64}$";
				Pattern pattern=Pattern.compile(regex);
				Matcher matcher = pattern.matcher(user.getName());
				if (!matcher.matches())
				{
					flag = false;
					this.put_error_msg("username", langRes.get("user.username-format-error"));
				}
				else
				{
					User dummy = UserService.getByName(user.getName());
					if (dummy != null &&
							(user.getId() == 0 || (user.getId() > 0 && dummy.getId() != user.getId())))
					{
						flag = false;
						this.put_error_msg("username", langRes.get("user.username-already-exists"));
					}
				}
			}

			// Email
			if (!StringUtils.isEmailAddress(user.getEmail()))
			{
				flag = false;
				this.put_error_msg("useremail", langRes.get("user.email-invalid"));
			}
			else
			{
				User dummy = UserService.getByEmail(user.getEmail());
				if (dummy != null &&
						(user.getId() == 0 || (user.getId() > 0 && dummy.getId() != user.getId())))
				{
					flag = false;
					this.put_error_msg("useremail", langRes.get("user.email-already-exists"));
				}
			}

			// Password
			if (user.getId() == 0 && passwd.length() == 0)
			{
				flag = false;
				this.put_error_msg("passwd", langRes.get("global.content-cannot-be-empty"));
			}
			else if (passwd.length() > 0)
			{
				if (!passwd.equals(passwd_confirm))
				{
					flag = false;
					this.put_error_msg("passwd", langRes.get("user.password-not-match"));
					this.put_error_msg("passwd_confirm", langRes.get("user.password-not-match"));
				}
				else
				{
					user.setPassword(StringDigest.hash(passwd));
				}
			}
			return flag;
		}
	}

	private void updateUserStatus(User user, int status)
	{
		if (status < 0 || status > UserService.STATUSES.length - 1) status = 0;
		if (user != null)
		{
			user.setStatus(status);
			UserService.updateUser(user);
		}
	}

	private String buildPermissionOptions(String permissions, String elementName)
	{
		String[] values = new String[SimpleConfig.getRoles().size()];
		String[] names = new String[SimpleConfig.getRoles().size()];
		List<String> selected = new ArrayList<String>();
		for (int i=0; i<SimpleConfig.getRoles().size(); i++)
		{
			int index = SimpleConfig.getRoleIndex(SimpleConfig.getRoles().get(i));
			values[i] = index+"";
			names[i] = SimpleConfig.getRoles().get(i);
			if (ACLBuilder.IndexOf(permissions, index))
			{
				selected.add(index+"");
			}
		}

		return ComponentBuilder.buildCheckBoxes(
				null, 
				elementName, 
				values, 
				names, 
				selected.toArray(new String[]{})
			);
	}
}
